/**
 * Its use is to check for names that are allowed in certain contexts and decides if a certain field is editable or not
 * @author zulianp@lu.unisi.ch & lemmar@lu.unisi.ch
 */

package ch.unisi.inf.projects.java.uom.gui;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import ch.unisi.inf.projects.java.uom.Constants;
import ch.unisi.inf.projects.java.uom.ConstantArrays;

import ch.unisi.inf.projects.java.uom.elements.Element;
import ch.unisi.inf.projects.java.uom.elements.Item;
import ch.unisi.inf.projects.java.uom.elements.ItemClass;
import ch.unisi.inf.projects.java.uom.elements.ItemManager;
import ch.unisi.inf.projects.java.uom.elements.ItemManagerListener;
import ch.unisi.inf.projects.java.uom.gui.itemclasseditor.UOMTripleEntryEmbeeder;

public final class NameController implements ItemManagerListener{

	private final ItemManager manager = ItemManager.instance();
	private final HashSet<String> itemClassNames;
	private final HashSet<String> itemNames;
	private static NameController instance;
	private String lastControlMessage;
	private final String[] nonEditableFields;
	
	private NameController()
	{
		itemClassNames = new HashSet<String>();
		itemNames = new HashSet<String>();
		manager.addItemManagerListener(this);
		nonEditableFields = new String[]{ "MULTIMEDIA" , Constants.ITEM_PRIMARY_KEY.value(), 
				Constants.ITEM_HASPREVIEW_FIELD.value(), Constants.ITEM_CATEGORY_FIELD.value()};
		if (!ItemManager.instance().databaseIsOpen())
			return;
		
		try {
				final Set<ItemClass> itemClasses = manager.getItemClasses();
				for(final ItemClass itemClass : itemClasses)
					itemClassNames.add(itemClass.getName());
				
		} catch (Exception ex) {
			ex.printStackTrace();
			lastControlMessage = "unable to load Category names.";
		}
		try { 
				Set<Item> items = manager.getItems();
				for(Item item : items)
				itemNames.add(item.getName());
				
		}
		catch (Exception ex) {
			ex.printStackTrace();
			lastControlMessage += " unable to load Items names.";
		}
	}
	
	public static NameController instance()
	{
		if(instance == null)
		instance = new NameController();
		return instance;
		
	}
	public boolean isValidSyntax(final String name)
	{
		if((name == null) || (name.length() == 0) || (!name.matches(Constants.REGEX.value()))){
			return false;}
		else return true;
	
	}
	public boolean validItemClassName(final String name)
	{
		lastControlMessage = "ok";
		if(!isValidSyntax(name) || name.contains(" ")) {
			lastControlMessage = "< " + name + " > contains illegal characters!";
			return false;
		}
		for(final String forbiddenName : ConstantArrays.ITEM_FORBIDDEN_ITEMCLASS.value()){
			if(name.equals(forbiddenName)){
				lastControlMessage = "< " + name + " > forbidden";
				return false;
			}
		}
		for(final String itemClassName : itemClassNames){
			if(name.equals(itemClassName)){
				lastControlMessage = "< " + name + " > Category already existing!" +'\n' + "Choose a different name!";
				return false;
			}
		}
		
		return true;
	}
	
	
	public boolean validEntryName(final ArrayList<UOMTripleEntryEmbeeder> embeeders)
	{
		boolean isValid = true;
		return isValid;
	}
	
	
	public boolean validFieldNames(final Set<String> names)
	{
		lastControlMessage = "Ok!";
		String SyntaxErrors = "Illegal characters in: " + '\n';
		boolean isValid = true;
		for(String name : names){
			if(!isValidSyntax(name))
			{
				SyntaxErrors += name + "," + '\n';
				isValid = false;
			}	
		}
		if(!isValid)
		{
			lastControlMessage = SyntaxErrors;
		}
		return isValid;
	}
	
	public boolean isEditableField(final String fieldKey)
	{
		boolean isEditable = true;
		for(String f : nonEditableFields)
		{
			isEditable = isEditable & !fieldKey.contains(f);
		}
		return isEditable;
	}

	public String getLastControlMessage()
	{
		return lastControlMessage;
	}
	
	// listening methods implementation

	public void elementDeleted(final Element e) {
		final String name = e.getName();
		if(e instanceof ItemClass)
			itemClassNames.remove(name);
		if(e instanceof Item)
			itemNames.remove(name);
	}

	

	public void itemAdded(final Item i) {
		itemNames.add(i.getName());
	}

	public void itemClassAdded(final ItemClass c) {
		itemClassNames.add(c.getName());
	}
	public void databaseClosed() {return;}
	public void databaseOpened() {return;}
	public void focusOnItem (final Item i) {return;}
	public void elementModified(final Element e) {return;}
		
}
